package com.ynhenc.pta.routeRank.impl;

import java.util.*;
import java.awt.geom.Point2D;
import java.io.*;

import com.mappers.jrps.second.Option;
import com.ynhenc.comm.db.*;
import com.ynhenc.pta.routeRank.*;

public abstract class SectionListOracle extends SectionListVehicle {

	public SectionListOracle(TransitType transitType, RouteRequest routeRequest) {
		super(transitType);
		this.routeRequest = routeRequest;
	}

	abstract public String getSqlNameRoute();

	abstract public String getSqlNamePath();

	abstract public String getRouteDescription(String routeNo);

	abstract public double getSearchRadius();

	public int getOptionRoute() {
		return Option.MODE_OPIMUM; // 최단 시간 경로.
	}

	final protected Section getSection(String routeId, int routeSeqA1, int routeSeqA2, String nodeNameStart, String nodeNameEnd, String sRouteNo) throws Exception {
		// 수행 속도 체크 시작.
		DurationChecker durationChecker = new DurationChecker(); 
		durationChecker.checkNow();
		// 끝. 수행 속도 체크 시작.

		String sqlText = "";

		if (true) { // reads sql statement from file
			String sqlSrc = this.getSqlNamePath();
			SQL sql = this.getSQL(sqlSrc);
			sqlText = sql.getSqlText();
			sqlText = sqlText.replaceAll("&ROUTE_ID", routeId);
			sqlText = sqlText.replaceAll("&ROUTE_SEQ_A1", "" + routeSeqA1);
			sqlText = sqlText.replaceAll("&ROUTE_SEQ_A2", "" + routeSeqA2);
		} // end of reading sql statement from file

		PathImpl path = new PathImpl();
		StartEndNode seNode = null;
		if (true) {
			Node sNode = new Node(nodeNameStart, 0, 0);
			Node eNode = new Node(nodeNameEnd, 0, 0);
			String desc = this.getRouteDescription(sRouteNo);
			seNode = new StartEndNode(this.getTransitType(), sNode, eNode, desc);
		}
		SectionImpl section = new SectionImpl(seNode, path); 
		QueryResult qr = this.getQueryResult(sqlText); 
		VertexSetList setList = new VertexSetList(); 
		int cnt = 0; 
		if (true) { // make vertex set list
			int index = 0;
			double wgs_x, wgs_y;
			Integer sectionIdPrev = null;
			Integer sectionIdCurr;
			VertexSet vertexSet = null;
			while (qr.hasNext()) {
				wgs_x = qr.getDouble("wgs_x");
				wgs_y = qr.getDouble("wgs_y");
				sectionIdCurr = qr.getInteger("SECTIONID");
				if (sectionIdPrev == null) {
					sectionIdPrev = sectionIdCurr;
				}
				if (!sectionIdCurr.equals(sectionIdPrev) || vertexSet == null) {
					vertexSet = new VertexSet();
					setList.add(vertexSet);
					sectionIdPrev = sectionIdCurr;
				}
				vertexSet.add(new Vertex(wgs_x, wgs_y));
				cnt++;
			} 
		} // end of making vertex set list

		if (setList.size() > 1) { // reverse partially if size > 1
			for (int i = 0, iLen = setList.size() - 1; i < iLen; i++) {
				VertexSetList.swapVertexSet(setList.get(i), setList.get(i + 1));
			}
		} // end of reversing paritally

		if (true) { // make up path
			int index = 0;
			for (VertexSet vertexSet : setList) {
				for (Vertex vertex : vertexSet) {
					if (index < 1 || index == cnt - 1) {
						String nodeName = (index < 1) ? nodeNameStart : nodeNameEnd;
						path.addVertex(new Node(vertex.getX(), vertex.getY(), nodeName));
					} else {
						path.addVertex(vertex);
					}
					index++;
				}
			}
		} // end of making path
		
		// 수행 속도 설정.
		durationChecker.checkNow(); 
		section.setQueryTime_Sec( durationChecker.getDuration() );
		// 끝. 수행속도 설정.
		
		qr.close();

		return section;

	}

	final public SectionList getSectionList(StartEndNode seNode) throws Exception {

		this.debug("seNode:" + seNode);
		// 여분의 수행 속도 체크 시작.
		DurationChecker durationChecker = new DurationChecker(); 
		durationChecker.checkNow();
		// 끝. 여분의 수행 속도 체크 시작.

		SectionList sectionList = new SectionList();

		String sqlText = "";

		if (true) { // reads sql statement from file
			String sqlSrc = this.getSqlNameRoute();
			SQL sql = this.getSQL(sqlSrc);
			sqlText = sql.getSqlText();
			if (true) {
				double radius = this.getSearchRadius();
				this.debug("RADIUS:" + radius);
				sqlText = sqlText.replaceAll("&RADIUS", "" + radius);
			}

			if (true) {
				if (true) { // start node
					Node node = seNode.getStartNode();
					Vertex tm = node.getWgs84ToTm();
					this.debug("TM:" + tm);
					sqlText = sqlText.replaceAll("&STARTX", "" + tm.getX());
					sqlText = sqlText.replaceAll("&STARTY", "" + tm.getY());
				}
				if (true) { // end node
					Node node = seNode.getEndNode();
					Point2D tm = node.getWgs84ToTm();
					this.debug("TM:" + tm);
					sqlText = sqlText.replaceAll("&ENDX", "" + tm.getX());
					sqlText = sqlText.replaceAll("&ENDY", "" + tm.getY());
				}
			}
		} // end of reading sql statement from file

		QueryResult qr = this.getQueryResult(sqlText);

		RecordRouteList routeList = new RecordRouteList();

		while (qr.hasNext()) {
			RecordRoute route = new RecordRoute(qr);
			this.debug("Route = " + route);
			routeList.add(route);
		}
		
		// 끝. 여분의 수행 속도 체크
		durationChecker.checkNow();
		sectionList.setExtraQueryTime_Sec( durationChecker.getDuration() );
		// 끝. 여분의 수행 속도 체크.

		for (int i = 0, iLen = 1; i < iLen && routeList.size() > 0; i++) { // make
			// section
			// object
			RecordRoute route = routeList.get(i);
			if (route.xType == 1) { // 직통. direct route
				String routeId = route.sRouteID;
				int routeSeqA1 = route.routeSeq_A1;
				int routeSeqA2 = route.routeSeq_B2;
				String nodeNameStart = route.sStationName;
				String nodeNameEnd = route.eStationName;
				String sRouteNo = route.sRouteNo;
				Section section = this.getSection(routeId, routeSeqA1, routeSeqA2, nodeNameStart, nodeNameEnd, sRouteNo);
				section.setLength_Meter(route.getTotalDistance_Meter()); // set
																			// total
																			// distance
				section.setTime_Sec(route.getTotalDuration_Sec()); // set totoal time after
				// converting to seconds
				sectionList.add(section);
				// end of direct route
			} else if (route.xType == 2) { // 환승. transfer route
				if (true) { // 앞에 구간.
					String routeId = route.sRouteID;
					int routeSeqA1 = route.routeSeq_A1;
					int routeSeqA2 = route.routeSeq_A2;
					String nodeNameStart = route.sStationName;
					String nodeNameEnd = route.tStationName;
					String sRouteNo = route.sRouteNo;
					Section section = this.getSection(routeId, routeSeqA1, routeSeqA2, nodeNameStart, nodeNameEnd, sRouteNo);
					section.setLength_Meter(route.getSTDistance_Meter()); // set total distance
					
					section.setTime_Sec( route.getSTDuration_Sec() ); // set totoal time
					// after converting
					// to seconds
					sectionList.add(section);
				} // end of first section
				if (true) { // 뒤 구간.
					String routeId = route.eRouteID;
					int routeSeqA1 = route.routeSeq_B1;
					int routeSeqA2 = route.routeSeq_B2;
					String nodeNameStart = route.tStationName;
					String nodeNameEnd = route.eStationName;
					String eRouteNo = route.eRouteNo;
					Section section = this.getSection(routeId, routeSeqA1, routeSeqA2, nodeNameStart, nodeNameEnd, eRouteNo);
					section.setLength_Meter(route.getTEDistance_Meter()); // set total
																// distance
					section.setTime_Sec( route.getTEDuration_Sec() ); // set totoal time
					// after converting
					// to seconds
					sectionList.add(section);
				} // end of second section
			}
		} // end of making section object

		qr.close();

		return sectionList;
	}

	public RouteRequest getRouteRequest() {
		return this.routeRequest;
	}

	private RouteRequest routeRequest;

}
